using UnityEngine;

/// <summary>
/// 边界传送控制器：实现物体到达指定边界时的无缝传送功能
/// 核心特性：
/// - 支持X轴(左右)和Z轴(上下)四个独立边界的自定义设置
/// - 可分别启用/禁用各轴的传送功能
/// - 包含边界值验证和自动纠错机制
/// - 在Scene视图中提供可视化边界调试
/// 应用场景：无限滚动背景、开放世界边界处理、屏幕环绕效果
/// <para>使用方法：</para>
/// <para>1. 将脚本挂载到需要边界传送的物体上</para>
/// <para>2. 在Inspector面板设置以下参数：</para>
/// <para>   - X轴边界：设置左/右边界值并启用X轴传送</para>
/// <para>   - Z轴边界：设置下/上边界值并启用Z轴传送</para>
/// <para>3. 运行场景，物体将在接触边界时自动传送</para>
/// <para>调试提示：选中物体可在Scene视图查看青色边界线</para>
/// </summary>
public class BoundaryTeleporter : MonoBehaviour
{
    #region 可配置边界参数
    /// <summary>
    /// 边界参数配置区域
    /// 注意事项：
    /// 1. 左边界必须小于右边界，下边界必须小于上边界
    /// 2. 边界值应根据实际场景大小合理设置
    /// 3. 禁用某轴传送不会影响其他轴功能
    /// </summary>

    [Header("X轴边界设置")]
    /// <summary>
    /// X轴左边界坐标值
    /// 当物体X坐标小于此值时将被传送到右边界
    /// 建议值：场景左边缘X坐标 - 物体碰撞半径
    /// </summary>
    [Tooltip("X轴左边界坐标值，物体小于此值将被传送到右边界")]
    public float xLeftBoundary = -10f;
    /// <summary>
    /// X轴右边界坐标值
    /// 当物体X坐标大于此值时将被传送到左边界
    /// 建议值：场景右边缘X坐标 + 物体碰撞半径
    /// </summary>
    [Tooltip("X轴右边界坐标值，物体大于此值将被传送到左边界")]
    public float xRightBoundary = 10f;
    /// <summary>
    /// 控制是否启用X轴方向的边界传送
    /// true: 启用传送功能
    /// false: 禁用传送功能，物体可自由超出X轴边界
    /// </summary>
    [Tooltip("是否启用X轴方向的边界传送功能")]
    public bool enableXWrapping = true;

    [Header("Z轴边界设置")]
    /// <summary>
    /// Z轴下边界坐标值
    /// 当物体Z坐标小于此值时将被传送到上边界
    /// 建议值：场景下边缘Z坐标 - 物体碰撞半径
    /// </summary>
    [Tooltip("Z轴下边界坐标值，物体小于此值将被传送到上边界")]
    public float zBottomBoundary = -10f;
    /// <summary>
    /// Z轴上边界坐标值
    /// 当物体Z坐标大于此值时将被传送到下边界
    /// 建议值：场景上边缘Z坐标 + 物体碰撞半径
    /// </summary>
    [Tooltip("Z轴上边界坐标值，物体大于此值将被传送到下边界")]
    public float zTopBoundary = 10f;
    /// <summary>
    /// 控制是否启用Z轴方向的边界传送
    /// true: 启用传送功能
    /// false: 禁用传送功能，物体可自由超出Z轴边界
    /// </summary>
    [Tooltip("是否启用Z轴方向的边界传送功能")]
    public bool enableZWrapping = true;

    #endregion

    #region 生命周期方法

    /// <summary>
    /// 初始化检查边界值有效性
    /// 在对象实例化时执行一次边界配置验证
    /// 防止因错误配置导致的传送异常
    /// </summary>
    private void Awake()
    {
        // 验证X轴边界设置：左边界必须小于右边界
        // 如果配置无效，自动禁用X轴传送并输出警告
        if (enableXWrapping && xLeftBoundary >= xRightBoundary)
        {
            Debug.LogWarning("X轴左边界必须小于右边界！已自动禁用X轴传送功能。");
            enableXWrapping = false;
        }

        // 验证Z轴边界设置：下边界必须小于上边界
        // 如果配置无效，自动禁用Z轴传送并输出警告
        if (enableZWrapping && zBottomBoundary >= zTopBoundary)
        {
            Debug.LogWarning("Z轴下边界必须小于上边界！已自动禁用Z轴传送功能。");
            enableZWrapping = false;
        }
    }

    /// <summary>
    /// 每帧检查物体位置并处理边界传送
    /// 调用频率：每帧一次（约60次/秒）
    /// 注意：如果物体移动速度极快，可能需要使用FixedUpdate确保不跳过边界检查
    /// </summary>
    private void Update()
    {
        CheckAndTeleport();
    }

    #endregion

    #region 边界检查与传送逻辑

    /// <summary>
    /// 核心逻辑：检查物体位置是否超出边界并执行传送
    /// 工作流程：
    /// 1. 获取物体当前位置
    /// 2. 分别检查X轴和Z轴是否超出边界
    /// 3. 对超出边界的轴执行对应边界的传送
    /// 4. 如果位置有变化则应用新位置
    /// </summary>
    private void CheckAndTeleport()
    {
        // 记录当前位置用于检查
        Vector3 currentPosition = transform.position;
        // 位置变化标志：优化性能，避免不必要的位置更新
        bool positionChanged = false;

        // 处理X轴边界传送：仅在启用时执行
        if (enableXWrapping)
        {
            if (currentPosition.x < xLeftBoundary)
            {
                currentPosition.x = xRightBoundary;
                positionChanged = true;
            }
            else if (currentPosition.x > xRightBoundary)
            {
                currentPosition.x = xLeftBoundary;
                positionChanged = true;
            }
        }

        // 处理Z轴边界传送
        if (enableZWrapping)
        {
            if (currentPosition.z < zBottomBoundary)
            {
                currentPosition.z = zTopBoundary;
                positionChanged = true;
            }
            else if (currentPosition.z > zTopBoundary)
            {
                currentPosition.z = zBottomBoundary;
                positionChanged = true;
            }
        }

        // 如果位置有变化则应用新位置
        if (positionChanged)
        {
            transform.position = currentPosition;
        }
    }

    #endregion

    #region Gizmos绘制

    /// <summary>
    /// 在Scene视图中绘制边界Gizmos，辅助场景调试
    /// 可视化效果：
    /// - 青色线条表示当前启用的边界
    /// - 线条仅在选中挂载脚本的物体时显示
    /// - 线条高度固定在Y=0.1f平面，避免与地面或其他物体重叠
    /// 使用方法：在Scene视图中选择挂载此脚本的物体即可看到边界线
    /// </summary>
    private void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.cyan;

        // 绘制X轴边界
        if (enableXWrapping && xLeftBoundary < xRightBoundary)
        {
            Vector3 leftBoundaryStart = new Vector3(xLeftBoundary, 0.1f, zBottomBoundary);
            Vector3 leftBoundaryEnd = new Vector3(xLeftBoundary, 0.1f, zTopBoundary);
            Vector3 rightBoundaryStart = new Vector3(xRightBoundary, 0.1f, zBottomBoundary);
            Vector3 rightBoundaryEnd = new Vector3(xRightBoundary, 0.1f, zTopBoundary);

            // 绘制左边界线：从下边界到上边界
            Gizmos.DrawLine(leftBoundaryStart, leftBoundaryEnd);
            // 绘制右边界线：从下边界到上边界
            Gizmos.DrawLine(rightBoundaryStart, rightBoundaryEnd);
        }

        // 绘制Z轴边界
        if (enableZWrapping && zBottomBoundary < zTopBoundary)
        {
            Vector3 bottomBoundaryStart = new Vector3(xLeftBoundary, 0.1f, zBottomBoundary);
            Vector3 bottomBoundaryEnd = new Vector3(xRightBoundary, 0.1f, zBottomBoundary);
            Vector3 topBoundaryStart = new Vector3(xLeftBoundary, 0.1f, zTopBoundary);
            Vector3 topBoundaryEnd = new Vector3(xRightBoundary, 0.1f, zTopBoundary);

            // 绘制下边界线：从左边界到右边界
            Gizmos.DrawLine(bottomBoundaryStart, bottomBoundaryEnd);
            // 绘制上边界线：从左边界到右边界
            Gizmos.DrawLine(topBoundaryStart, topBoundaryEnd);
        }
    }

    #endregion
}